package com.hsy.crm.web.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hsy.crm.web.domain.cm.App;
import com.hsy.crm.web.domain.cm.PageResult;
import com.hsy.crm.web.domain.cm.Unified;
import com.hsy.crm.web.domain.entity.*;
import com.hsy.crm.web.domain.po.product.ProductExportPo;
import com.hsy.crm.web.domain.po.product.ProductGetPo;
import com.hsy.crm.web.domain.po.product.ProductPagePo;
import com.hsy.crm.web.domain.po.unit.ProductUnitPo;
import com.hsy.crm.web.domain.vo.product.ProductInsertVo;
import com.hsy.crm.web.domain.vo.product.ProductMultiUnitVo;
import com.hsy.crm.web.domain.vo.product.ProductPageVo;
import com.hsy.crm.web.domain.vo.report.ExcelVo;
import com.hsy.crm.web.domain.vo.unit.ProductUnitVo;
import com.hsy.crm.web.mapper.*;
import com.hsy.crm.web.service.base.BaseService;
import com.hsy.crm.web.utils.ListUtils;
import com.hsy.crm.web.utils.StringUtils;
import com.hsy.crm.web.utils.UuidUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class ProductService extends BaseService<Product> {

    @Autowired
    ProductMapper productMapper;

    @Autowired
    ProductPriceMapper productPriceMapper;

    @Autowired
    ProductMultiUnitMapper multiUnitMapper;

    @Autowired
    StoreProductMapper storeProductMapper;

    @Autowired
    UnitMapper unitMapper;

    @Transactional
    public Unified<Integer> insertProduct(ProductInsertVo productInsertVo) {
        Unified<Integer> unified = Unified.create(Integer.class);

        // check
        int checkResult = insertCheck(productInsertVo);
        if(checkResult != App.Result.SUCCESS){
            unified.setResult(checkResult);
            return unified;
        }

        // insert product
        Product product = productInsertVo.getProduct();
        product.setLoginUserId(productInsertVo.getLoginUserId());
        product.setLoginCompanyId(productInsertVo.getLoginCompanyId());
        product.setCustomerId(productInsertVo.getCustomerId());
        product.setLastPurchasePrice(0L);
        product.setLastSalePrice(0L);

        int result = this.insert(product,Boolean.TRUE);
        if( result == 0 ){
            unified.setResult(App.BussError.NAME_REPEAT.getCode());
            return unified;
        }

        // insert product price
        this.insertProductPrice(productInsertVo);

        // insert product units
        this.insertProductUnits(productInsertVo);

        return unified;
    }

    @Transactional
    public Unified<Integer> updateProduct(ProductInsertVo productInsertVo) {
        Unified<Integer> unified = Unified.create(Integer.class);

        // check
        int checkResult = updateCheck(productInsertVo);
        if(checkResult != App.Result.SUCCESS){
            unified.setResult(checkResult);
            return unified;
        }

        // insert product
        Product product = productInsertVo.getProduct();
        product.setLoginUserId(productInsertVo.getLoginUserId());
        product.setLoginCompanyId(productInsertVo.getLoginCompanyId());
        product.setCustomerId(productInsertVo.getCustomerId());
        this.update(product, App.Boolean.TRUE);

        this.deleteProductPrice(product);
        this.deleteProductUnits(product);

        // insert product price
        this.insertProductPrice(productInsertVo);
        // insert product units
        this.insertProductUnits(productInsertVo);

        return unified;
    }

    @Transactional
    public Unified<Integer> deleteProduct(Product product) {
        Unified<Integer> unified = new Unified<>();

        int checkResult = deleteCheck(product);
        if(checkResult != App.Result.SUCCESS){
            unified.setResult(checkResult);
            return unified;
        }

        StoreProduct storeProduct = new StoreProduct();
        storeProduct.setProductId(product.getId());
        storeProduct.setCustomerId(product.getCustomerId());
        storeProductMapper.delete(storeProduct);
        this.delete(product);
        this.deleteProductPrice(product);
        this.deleteProductUnits(product);
        return unified;
    }

    public PageResult<ProductPagePo> page(ProductPageVo productPageVo) {
        Page page = PageHelper.startPage(productPageVo.getPage(),productPageVo.getLimit());
        PageResult<ProductPagePo> pageResult = new PageResult<>();

        if(productPageVo.getCompanyId()==null){
            productPageVo.setCompanyId(productPageVo.getLoginCompanyId());
        }

        pageResult.setRows(productMapper.page(productPageVo));
        pageResult.setTotal(page.getTotal());
        return pageResult;
    }

    public PageResult<Product> choose(ProductPageVo productPageVo) {
        Page page = PageHelper.startPage(productPageVo.getPage(),productPageVo.getLimit());
        PageResult<Product> pageResult = new PageResult<>();
        productPageVo.setCompanyId(productPageVo.getLoginCompanyId());
        if( StringUtils.isEmpty(productPageVo.getProductTypeLogicalCode()) ){
            pageResult.setRows(productMapper.choose(productPageVo));
        }else{
            pageResult.setRows(productMapper.chooseByProductType(productPageVo));
        }

        pageResult.setTotal(page.getTotal());
        return pageResult;
    }

    public ProductPagePo getByBarcode(ProductPageVo productPageVo){

        if(StringUtils.isEmpty(productPageVo.getBarcode())){
            return new ProductPagePo();
        }

        productPageVo.setCompanyId(productPageVo.getLoginCompanyId());
        List<ProductPagePo> productPagePos =  productMapper.page(productPageVo);
        if( ListUtils.isEmpty(productPagePos) ){
            return new ProductPagePo();
        }else{
            return productPagePos.get(0);
        }
    }

    public PageResult<ProductPagePo> chose(ProductPageVo productPageVo) {
        Page page = PageHelper.startPage(productPageVo.getPage(),productPageVo.getLimit());
        PageResult<ProductPagePo> pageResult = new PageResult<>();
        pageResult.setRows(productMapper.chose(productPageVo));
        pageResult.setTotal(page.getTotal());
        return pageResult;
    }

    public Unified<ProductGetPo> get(Product product) {
        Unified<ProductGetPo> unified = new Unified<>();
        ProductGetPo productGetPo = new ProductGetPo();

        //product
        productGetPo.setProduct(productMapper.getProduct(product));

        //product price
        ProductPrice productPrice = new ProductPrice();
        productPrice.setProductId(product.getId());
        productPrice.setCustomerId(product.getCustomerId());
        productGetPo.setProductPrice(productPriceMapper.selectOne(productPrice));

        //product units
        List<ProductUnitPo> productUnitPos = productMapper.getMultiUnits(product);
        productGetPo.setUnits(productUnitPos);

        unified.setData(productGetPo);
        return unified;
    }


    /**
     * 查询商品的所有单位
     * @param productUnitVo
     * @return
     */
    public Unified<List<ProductUnitPo>> getUnit(ProductUnitVo productUnitVo){
        Unified<List<ProductUnitPo>> unified = new Unified<>();

        // find product
        Product product = new Product();
        product.setId(productUnitVo.getProductId());
        product.setCustomerId(productUnitVo.getCustomerId());
        product = productMapper.selectByPrimaryKey(product);
        product.setCustomerId(productUnitVo.getCustomerId());

        // product unit
        Unit unit = new Unit();
        unit.setId(product.getUnitId());
        unit.setCustomerId(productUnitVo.getCustomerId());
        unit = unitMapper.selectOne(unit);

        // product multi unit

        List<ProductUnitPo> unitPos = productMapper.getMultiUnits(product);
        unitPos.add(new ProductUnitPo(unit));

        unified.setData(unitPos);
        return unified;
    }

    public Unified<List<ProductUnitPo>> getMultiUnit(ProductUnitVo productUnitVo){
        Unified<List<ProductUnitPo>> unified = new Unified<>();

        // product multi unit
        Product product = new Product();
        product.setCustomerId(productUnitVo.getCustomerId());
        product.setId(productUnitVo.getProductId());
        List<ProductUnitPo> unitPos = productMapper.getMultiUnits(product);

        unified.setData(unitPos);
        return unified;
    }

    public List<ProductExportPo> findProductData(ExcelVo excelVo){
        return productMapper.findProductData(excelVo);
    }

    private Unit insertOrGetUnit(String unitName,ProductInsertVo productInsertVo){
        Unit unit = new Unit();
        unit.setName(unitName);
        unit.setCustomerId(productInsertVo.getCustomerId());
        List<Unit> units = unitMapper.select(unit);
        if( units != null && units.size()==1 ){
            return units.get(0);
        }else{
            return insertUnit(unitName,productInsertVo);
        }
    }

    private Unit insertUnit(String unitName,ProductInsertVo productInsertVo){
        Unit unit = new Unit();
        unit.setLoginUserId(productInsertVo.getLoginUserId());
        unit.setId(UuidUtils.getUuid());
        unit.setName(unitName);
        unit.setType(App.UnitType.SLAVE);
        unit.setCustomerId(productInsertVo.getCustomerId());
        unit.setCompanyId(productInsertVo.getLoginCompanyId());
        unit.setLoginCompanyId(productInsertVo.getLoginCompanyId());
        unitMapper.insert(unit);
        return unit;
    }

    private int insertCheck(ProductInsertVo productInsertVo){

        //check units
        int result = unitsCheck(productInsertVo);
        if( result == App.Result.PARAM_ERROR ){
            return result;
        }

        //check code
        Product codeProduct = new Product();
        codeProduct.setCode(productInsertVo.getProduct().getCode());
        codeProduct.setCustomerId(productInsertVo.getCustomerId());
        codeProduct.setCompanyId(productInsertVo.getProduct().getCompanyId());
        Long productId = productMapper.checkCode(codeProduct);
        if( productId != null ){
            return App.BussError.CODE_REPEAT.getCode();
        }

        //check bar code
        if(!StringUtils.isEmpty(productInsertVo.getProduct().getBarcode())){
            Product barcodeProduct = new Product();
            barcodeProduct.setBarcode(productInsertVo.getProduct().getBarcode());
            barcodeProduct.setCompanyId(productInsertVo.getProduct().getCompanyId());
            barcodeProduct.setCustomerId(productInsertVo.getCustomerId());
            productId = productMapper.checkBarcode(barcodeProduct);
            if( productId != null ){
                return App.BussError.BARCODE_REPEAT.getCode();
            }
        }

        return App.Result.SUCCESS;
    }

    private int updateCheck(ProductInsertVo productInsertVo){

        //check units
        int result = unitsCheck(productInsertVo);
        if( result == App.Result.PARAM_ERROR ){
            return result;
        }

        //check code
        Product product = productInsertVo.getProduct();
        product.setCustomerId(productInsertVo.getCustomerId());
        product.setLoginCompanyId(productInsertVo.getLoginCompanyId());
        if(this.updateCheckCode(productInsertVo)){
            return App.BussError.CODE_REPEAT.getCode();
        }
        if(this.updateCheckBarCode(productInsertVo)){
            return App.BussError.BARCODE_REPEAT.getCode();
        }

        return App.Result.SUCCESS;
    }

    protected boolean updateCheckCode(ProductInsertVo productInsertVo){

        if(StringUtils.isEmpty(productInsertVo.getProduct().getBarcode())){
            return false;
        }

        //check code
        Product codeProduct = new Product();
        codeProduct.setBarcode(productInsertVo.getProduct().getBarcode());
        codeProduct.setCustomerId(productInsertVo.getCustomerId());
        codeProduct.setCompanyId(productInsertVo.getProduct().getCompanyId());
        Long productId = productMapper.checkCode(codeProduct);

        if( productId == null ){
            return false;
        }else{
            return productId.longValue() != productInsertVo.getProduct().getId().longValue();
        }
    }

    protected boolean updateCheckBarCode(ProductInsertVo productInsertVo){

        if(StringUtils.isEmpty(productInsertVo.getProduct().getBarcode())){
            return false;
        }

        //check bar code
        Product barcodeProduct = new Product();
        barcodeProduct.setBarcode(productInsertVo.getProduct().getBarcode());
        barcodeProduct.setCustomerId(productInsertVo.getCustomerId());
        barcodeProduct.setCompanyId(productInsertVo.getProduct().getCompanyId());
        Long productId = productMapper.checkBarcode(barcodeProduct);

        if( productId == null ){
            return false;
        }else{
            return productId.longValue() != productInsertVo.getProduct().getId().longValue();
        }
    }

    private int unitsCheck(ProductInsertVo productInsertVo){

        //check units
        if(productInsertVo.getProductMultiUnits()!=null){
            for (ProductMultiUnitVo unit : productInsertVo.getProductMultiUnits()){
                if(StringUtils.isEmpty(unit.getName()) || unit.getRate()==null){
                    return App.Result.PARAM_ERROR;
                }
            }
        }

        return App.Result.SUCCESS;
    }


    private int deleteCheck(Product product){

        // order detail check
        Long productId = productMapper.checkOrderDetail(product);
        if( productId != null ){
            return App.BussError.PRODUCT_DELETE_ORDER.getCode();
        }

        // not check stone

        return App.Result.SUCCESS;
    }

    private void deleteProductPrice(Product product){
        // insert product price
        ProductPrice productPrice = new ProductPrice();
        productPrice.setProductId(product.getId());
        productPrice.setCustomerId(product.getCustomerId());
        productPriceMapper.delete(productPrice);
    }

    private void insertProductPrice(ProductInsertVo productInsertVo){
        // insert product price
        ProductPrice productPrice = productInsertVo.getProductPrice();
        if( productPrice != null ){
            productPrice.setId(UuidUtils.getUuid());
            productPrice.setProductId(productInsertVo.getProduct().getId());
            productPrice.setCustomerId(productInsertVo.getCustomerId());
            productPriceMapper.insert(productPrice);
        }
    }

    private void deleteProductUnits(Product product){
        ProductMultiUnit multiUnit = new ProductMultiUnit();
        multiUnit.setProductId(product.getId());
        multiUnit.setCustomerId(product.getCustomerId());
        multiUnitMapper.delete(multiUnit);
    }

    private void insertProductUnits(ProductInsertVo productInsertVo){
        List<ProductMultiUnitVo> unitVos = productInsertVo.getProductMultiUnits();
        if( ListUtils.isNotEmpty(unitVos) ) {
            for( ProductMultiUnitVo unitVo : unitVos ){
                Unit unit = this.insertOrGetUnit(unitVo.getName(),productInsertVo);
                ProductMultiUnit multiUnit = new ProductMultiUnit();
                multiUnit.setCustomerId(productInsertVo.getCustomerId());
                multiUnit.setId(UuidUtils.getUuid());
                multiUnit.setUnitId(unit.getId());
                multiUnit.setProductId(productInsertVo.getProduct().getId());
                multiUnit.setRate(unitVo.getRate());
                multiUnitMapper.insert(multiUnit);

            }
        }
    }

}
